// This file contains everything specific to transports and transportation
var CB;
(function (CB) {
    var Transportation;
    (function (Transportation) {
        var cb = global.craig_brett;
        function make_transport(args) {
            var unit = args.unit;
            var capacity = args.capacity;
            var onEnter = args.onEnter;
            var onEnterArgs = args.onEnterArgs;
            var onExit = args.onExit;
            var onExitArgs = args.onExitArgs;
            var transportObj = {};
            if (capacity) {
                transportObj.capacity = capacity;
                transportObj.currentCapacity = 0;
            }
            if (onEnter) {
                transportObj.enterCallback = onEnter;
            }
            if (onEnterArgs) {
                transportObj.enterCallbackArgs = onEnterArgs;
            }
            if (onExit) {
                transportObj.exitCallback = onExit;
            }
            if (onExitArgs) {
                transportObj.exitCallbackArgs = onExitArgs;
            }
            transportObj.cargo = shared.MakeIntToObjectHash();
            cb.transports[unit.ID] = transportObj;
        }
        Transportation.make_transport = make_transport;
        function load_unit_into_transport(args) {
            /// <summary>Places the source unit inside the target unit</summary>
            var source = args.source;
            var target = args.target;
            var skill = args.skill;
            var success = args.success;
            if (skill && !success)
                return; // no entering transport on failed skills
            if (!cb.transports[target.ID]) {
                say("Unit cannot be loaded into the " + target.Type);
                return;
            }
            var transportObj = cb.transports[target.ID];
            var capacityCost;
            capacityCost = source.ScriptFlags.get("transport_capacity_required");
            if (typeof (capacityCost) != 'undefined' && typeof (transportObj.capacity) != 'undefined' && transportObj.currentCapacity + capacityCost > transportObj.capacity) {
                say("Unit cannot be loaded. Not enough capacity.");
                return;
            }
            shared.Map.RemoveUnit(source);
            transportObj.cargo[source.ID] = source;
            transportObj.currentCapacity += capacityCost;
            cb.transports[target.ID] = transportObj; // to update the held value
            if (skill.ScriptFlags.get("enters_transport_sound")) {
                sound(skill.ScriptFlags.get("enters_transport_sound"));
            }
            if (skill.ScriptFlags.get("enters_transport_message")) {
                var msg = CB.chooseFromARandomSelectString(skill.ScriptFlags.get("enters_transport_message"));
                say(msg.format(source.GetName(), target.GetName()));
            }
        }
        Transportation.load_unit_into_transport = load_unit_into_transport;
        function unload_all_transported_units(args) {
            /// <summary>Evacuates all loaded units from a transport</summary>
            var source = args.source;
            var target = args.target;
            var tile = args.tile;
            var skill = args.skill;
            var success = args.success;
            if (skill && !success)
                return; // don't unload on unsuccessful skills
            if (target == null && tile != null && source != null) {
                target = source;
            }
            var map = shared.Map; // just saving some typing
            if (!cb.transports[target.ID]) {
                say("This unit is not designated as a transport and cannot be unloaded");
                return;
            }
            var transportObj = cb.transports[target.ID];
            if (transportObj.currentCapacity == 0) {
                say("No units to unload from this transport.");
                return;
            }
            if (tile == null) {
                say("Taking the target's tile");
                tile = target.Tile;
            }
            var id;
            var tileNum = 0;
            var currentTile;
            var cargoKeys = transportObj.cargo.keys;
            for (var key = 0; key < cargoKeys.length; key++) {
                id = cargoKeys[key];
                var currentUnit = transportObj.cargo[id];
                var adjacentTileSearchStatus = 0; // 0 means still looking, 1 means success, -1 means shit done gone wrong
                while (adjacentTileSearchStatus == 0) {
                    switch (tileNum) {
                        case 0:
                            currentTile = tile;
                            break;
                        case 1:
                            if (tile.Y > 1) {
                                currentTile = map.GetTile(tile.X, tile.Y - 1);
                            } // else let it carry on, since it will just fail the checks below and start over
                            break;
                        case 2:
                            if (tile.X + 1 <= map.Width) {
                                currentTile = map.GetTile(tile.X + 1, tile.Y);
                            }
                            break;
                        case 3:
                            if (tile.Y + 1 <= map.Height) {
                                currentTile = map.GetTile(tile.X, tile.Y + 1);
                            }
                            break;
                        case 4:
                            if (tile.X > 1) {
                                currentTile = map.GetTile(tile.X - 1, tile.Y);
                            }
                            break;
                        default:
                            adjacentTileSearchStatus = -1;
                            break;
                    }
                    if (adjacentTileSearchStatus == -1) {
                        say("Unable to unload all units. Not enough useable space around the transport.");
                        return;
                    }
                    if (currentTile.CanHold(currentUnit) == true) {
                        map.AddUnit(currentUnit, currentTile.X, currentTile.Y);
                        transportObj.cargo.Remove(id);
                        transportObj.currentCapacity -= currentUnit.ScriptFlags.get("transport_capacity_required");
                        if (transportObj.exitCallback) {
                            var callback = transportObj.exitCallback;
                            var newEvent = {};
                            var argsObject;
                            if (transportObj.exitCallbackArgs) {
                                argsObject = transportObj.exitCallbackArgs;
                            }
                            else {
                                argsObject = {};
                            }
                            argsObject.source_unit = currentUnit;
                            argsObject.target_unit = target;
                            newEvent = CB.applyObjectToEvent(newEvent, argsObject, source.Type, target.Type);
                            callback(newEvent);
                        }
                        adjacentTileSearchStatus = 1;
                    }
                    else {
                        tileNum++;
                    }
                }
            }
            // update the transport object held on the global to reflect the new state
            cb.transports[target.ID] = transportObj;
            if (skill) {
                if (skill.ScriptFlags.get("unloads_transport_sound")) {
                    sound(skill.ScriptFlags.get("unloads_transport_sound"));
                }
                if (skill.ScriptFlags.get("unloads_transport_message")) {
                    var msg = CB.chooseFromARandomSelectString(skill.ScriptFlags.get("unloads_transport_message"));
                    say(msg.format(source.GetName(), target.GetName()));
                }
            }
        }
        Transportation.unload_all_transported_units = unload_all_transported_units;
        function adjust_transport_capacity(args) {
            /// <summary>Adjusts the target transport's capacity by a given amount, to a minimum of 0</summary>
            var target = args.target;
            var adjustment = args.adjustment;
            var newValue = cb.transports[target.ID].capacity + adjustment;
            if (newValue < 0) {
                newValue = 0;
            }
            cb.transports[target.ID].capacity = newValue;
        }
        Transportation.adjust_transport_capacity = adjust_transport_capacity;
        function announce_transport_capacity(args) {
            /// <summary>Announces the transports current and max capacity</summary>
            var output = "";
            if (args.k != args.key || args.m != args.mod) {
                return; // it's not the key combination we are supposed to respond to.
            }
            if (!args.format) {
                say("No format for reading transport capacity given.");
                return;
            }
            else {
                output = args.format;
            }
            var unit = shared.Map.ReviewTile.Selected;
            if (!unit) {
                say("No unit or structure selected.");
                return;
            }
            var transportObj = cb.transports[unit.ID];
            var current = 0, max = 0;
            if (transportObj) {
                current = transportObj.currentCapacity;
                max = transportObj.capacity;
            }
            say(output.format(current, max));
        }
        Transportation.announce_transport_capacity = announce_transport_capacity;
    })(Transportation = CB.Transportation || (CB.Transportation = {}));
})(CB || (CB = {}));
